// Package internal 数据处理
package internal

import (
	"context"
	"fmt"
	"sync"
	"time"

	"gitee.com/serialnumber/internal/models"
	"gitee.com/serialnumber/internal/supports"
	"github.com/micro/go-log"
)

// Generate struct
type Generate struct {
	readWg        supports.Wrapper
	writeWg       supports.Wrapper
	ctx           context.Context
	cancel        context.CancelFunc
	authType      int
	products      []*product
	productCh     chan *authAndProduct
	limited       sync.Map
	testRepo      models.ITest100Reposity
	exitWriteChan chan struct{}
	exitReadChan  chan struct{}
}

type authAndProduct struct {
	AuthType int
	ID       string
}

type product struct {
	ID      string
	CodeNum int
}

// NewGenerate instance
func NewGenerate(authType int) *Generate {
	g := &Generate{
		authType:      authType,
		products:      make([]*product, 0),
		productCh:     make(chan *authAndProduct, 100),
		exitReadChan:  make(chan struct{}),
		exitWriteChan: make(chan struct{}),
	}

	for i := 0; i < 100; i++ {
		g.products = append(g.products, &product{
			ID: fmt.Sprintf("%v-%v", "ABCDEF", i),
		})
		g.limited.Store(supports.GetMapKey(fmt.Sprintf("%v-%v", "ABCDEF", i), authType), 10000)
	}

	g.testRepo = &models.Test100Model{}
	g.ctx, g.cancel = context.WithCancel(context.Background())
	return g
}

// Run func
func (handle *Generate) Run() {
	for i := 0; i < 10; i++ {
		handle.readWg.Wrap(handle.readRoutine)
	}

	handle.writeWg.Wrap(handle.writeRoutine)
}

func (handle *Generate) writeRoutine() {
	for {
		select {
		case <-handle.exitWriteChan:
			log.Log("谁先来-----------退出协程", time.Now())
			return
		default:
			for _, v := range handle.products {
				handle.productCh <- &authAndProduct{
					AuthType: handle.authType,
					ID:       v.ID,
				}
			}
		}
	}
}

func (handle *Generate) readRoutine() {
	for {
		select {
		case <-handle.exitReadChan:
			log.Log("停止写数据库协程")
			return
		case v, ok := <-handle.productCh:
			if !ok {
				return
			}
			if err := handle.testRepo.Create(&models.Test100{
				Name: v.ID,
				Age:  v.AuthType,
			}); err != nil {
				log.Log("写入数据库失败啦啦啦啦", err)
			}
		}
	}
}

// Stop 释放资源
func (handle *Generate) Stop() {
	log.Log("释放实例--------------")
	handle.cancel()
	{
		close(handle.exitWriteChan)
		handle.writeWg.Wait()
		close(handle.productCh)
	}
	{
		close(handle.exitReadChan)
		handle.readWg.Wait()
	}
}
